"""
@-*- coding: utf-8 -*-
@ python: 3.12.3
@ 创建者: JacksonCode
@ 创建时间: 2025-11-06
@ 描述: 数据验证器
"""
import re
from typing import Any, Dict, List, Optional


def validate_email(email: str) -> bool:
    """验证邮箱格式"""
    if not email:
        return False
    
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, email) is not None


def validate_password(password: str) -> bool:
    """验证密码强度
    
    要求：
    - 至少8位
    - 包含至少一个字母
    - 包含至少一个数字
    """
    if not password or len(password) < 8:
        return False
    
    # 检查是否包含字母
    has_letter = bool(re.search(r'[a-zA-Z]', password))
    # 检查是否包含数字
    has_digit = bool(re.search(r'\d', password))
    
    return has_letter and has_digit


def validate_username(username: str) -> bool:
    """验证用户名
    
    要求：
    - 3-20个字符
    - 只能包含字母、数字、下划线和中文
    """
    if not username or len(username) < 3 or len(username) > 20:
        return False
    
    # 允许字母、数字、下划线和中文
    pattern = r'^[a-zA-Z0-9_\u4e00-\u9fa5]+$'
    return re.match(pattern, username) is not None


def validate_phone(phone: str) -> bool:
    """验证手机号格式（中国大陆）"""
    if not phone:
        return False
    
    pattern = r'^1[3-9]\d{9}$'
    return re.match(pattern, phone) is not None


def validate_id_card(id_card: str) -> bool:
    """验证身份证号格式（中国大陆）"""
    if not id_card:
        return False
    
    # 18位身份证号
    pattern = r'^\d{17}[\dXx]$'
    return re.match(pattern, id_card) is not None


def validate_required_fields(data: Dict[str, Any], required_fields: List[str]) -> Optional[str]:
    """验证必填字段
    
    Args:
        data: 要验证的数据字典
        required_fields: 必填字段列表
        
    Returns:
        如果验证通过返回None，否则返回缺失的字段名
    """
    if not isinstance(data, dict):
        return "数据格式错误"
    
    for field in required_fields:
        if field not in data or data[field] is None or data[field] == "":
            return field
    
    return None


def validate_field_length(value: str, min_length: int = 0, max_length: int = None) -> bool:
    """验证字段长度
    
    Args:
        value: 要验证的值
        min_length: 最小长度
        max_length: 最大长度
        
    Returns:
        验证通过返回True，否则返回False
    """
    if value is None:
        return min_length == 0
    
    length = len(value)
    
    if length < min_length:
        return False
    
    if max_length is not None and length > max_length:
        return False
    
    return True


def validate_numeric_range(value: Any, min_value: float = None, max_value: float = None) -> bool:
    """验证数值范围
    
    Args:
        value: 要验证的值
        min_value: 最小值
        max_value: 最大值
        
    Returns:
        验证通过返回True，否则返回False
    """
    try:
        num_value = float(value)
    except (ValueError, TypeError):
        return False
    
    if min_value is not None and num_value < min_value:
        return False
    
    if max_value is not None and num_value > max_value:
        return False
    
    return True


def validate_choice(value: Any, choices: List[Any]) -> bool:
    """验证选项值
    
    Args:
        value: 要验证的值
        choices: 可选值列表
        
    Returns:
        验证通过返回True，否则返回False
    """
    return value in choices


def validate_date_format(date_str: str, format: str = "%Y-%m-%d") -> bool:
    """验证日期格式
    
    Args:
        date_str: 日期字符串
        format: 日期格式
        
    Returns:
        验证通过返回True，否则返回False
    """
    try:
        import datetime
        datetime.datetime.strptime(date_str, format)
        return True
    except ValueError:
        return False


def sanitize_string(value: str) -> str:
    """清理字符串，移除潜在的恶意字符
    
    Args:
        value: 要清理的字符串
        
    Returns:
        清理后的字符串
    """
    if not value:
        return ""
    
    # 移除HTML标签
    import re
    value = re.sub(r'<[^>]+>', '', value)
    
    # 移除潜在的JavaScript代码
    value = re.sub(r'javascript:', '', value, flags=re.IGNORECASE)
    
    return value.strip()